package com.keqiang.chart.impl.axis.impl.line

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.DashPathEffect
import android.graphics.Paint
import android.text.Layout
import android.text.TextPaint
import androidx.annotation.ColorInt
import com.keqiang.chart.utils.ObjectPool
import com.keqiang.chart.utils.px
import com.keqiang.utils.PaintUtils
import com.keqiang.utils.PaintUtils.getChartHeight

/**
 * 折线图点击高亮默认实现
 *
 * @author Created by wanggaowan on 2022/5/31 15:47
 */
open class LineChartHighLightRender @JvmOverloads constructor(
    chart: LineChart, @ColorInt val lineColor: Int = Color.DKGRAY,
    val lineWidth: Float = 2f) : HighLightRender(chart) {

    override fun onDraw(canvas: Canvas, start: Float, top: Float, end: Float, bottom: Float, data: List<LineEntity>) {
        val tempPath = ObjectPool.obtainPath()
        val paint = ObjectPool.obtainPaint<Paint>()
        val textPaint = ObjectPool.obtainPaint<TextPaint>(true)
        paint.color = lineColor
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = lineWidth
        paint.pathEffect = DashPathEffect(floatArrayOf(10f, 10f), 0f)

        data.forEach {
            tempPath.reset()
            tempPath.moveTo(start, it.drawRectF.top)
            tempPath.lineTo(it.drawRectF.left, it.drawRectF.top)
            canvas.drawPath(tempPath, paint)

            tempPath.reset()
            tempPath.moveTo(it.drawRectF.left, bottom)
            tempPath.lineTo(it.drawRectF.left, it.drawRectF.top)
            canvas.drawPath(tempPath, paint)

            getText(it)?.let { text ->
                if (text.isNotEmpty()) {
                    textPaint.textSize = getTextSize(it)
                    textPaint.color = getTextColor(it)

                    // 测量指定文本每行的最大宽度
                    val split = text.split("\n")
                    var maxOneLineWidth = 0f
                    split.forEach { str ->
                        maxOneLineWidth = textPaint.measureText(str).coerceAtLeast(maxOneLineWidth)
                    }

                    var maxWidth = (end - start).toInt()
                    val textLine = PaintUtils.getTextLine(text, textPaint, maxWidth)
                    val chartHeight = textPaint.getChartHeight()
                    var align = Layout.Alignment.ALIGN_CENTER
                    val drawX = if (maxOneLineWidth > maxWidth) {
                        align = Layout.Alignment.ALIGN_NORMAL
                        start
                    } else {
                        maxWidth = maxOneLineWidth.toInt()
                        val cx = it.drawRectF.centerX()
                        if (cx - start >= maxOneLineWidth / 2f) {
                            if (cx + maxOneLineWidth / 2f > end) {
                                align = Layout.Alignment.ALIGN_OPPOSITE
                                end - maxOneLineWidth
                            } else {
                                cx - maxOneLineWidth / 2f
                            }
                        } else if (cx + maxOneLineWidth / 2f > end) {
                            align = Layout.Alignment.ALIGN_OPPOSITE
                            end - maxOneLineWidth
                        } else {
                            align = Layout.Alignment.ALIGN_NORMAL
                            start
                        }
                    }

                    val drawY = (it.drawRectF.top - chartHeight * textLine).coerceAtLeast(top)

                    canvas.save()
                    canvas.translate(drawX, drawY)
                    PaintUtils.drawText(canvas, textPaint, text, maxWidth, Int.MAX_VALUE, align)
                    canvas.restore()
                }
            }
        }

        ObjectPool.recyclePath(tempPath)
        ObjectPool.recyclePaint(paint)
        ObjectPool.recyclePaint(textPaint)
    }

    /**
     * 获取需要绘制的文本
     */
    open fun getText(lineEntity: LineEntity): CharSequence? = null

    /**
     * 获取需要绘制的字体大小
     */
    open fun getTextSize(lineEntity: LineEntity): Float = 16f.px

    /**
     * 获取需要绘制的字体颜色
     */
    open fun getTextColor(lineEntity: LineEntity): Int = Color.BLACK
}